home *** CD-ROM | disk | FTP | other *** search
- /* Kevo -- a prototype-based object-oriented language */
- /* (c) Antero Taivalsaari 1991-1993 */
- /* Some parts (c) Antero Taivalsaari 1986-1988 */
- /* portBrowser.c: Non-portable object browser */
-
- #include "global.h"
- #include "portGlobal.h"
-
- /*---------------------------------------------------------------------------*/
- /* Graphical user interface (GUI) initialization */
-
- /* Open and initialize the browser */
-
- void openBrowser(target, windowIdent, browserKind)
- OBJECT* target; /* The object to be browsed */
- char* windowIdent; /* The (partial) name of the window */
- int browserKind; /* Browser kind (either BrowserWKind or CloneBrWKind) */
- {
- WindowPtr browserWindow;
- WindowPtr frontWindow;
- GrafPtr savePort;
- WINFO* thisWinfo;
- ListHandle iconList;
- int wKind;
- int columns; /* Initial number of columns in the browser */
- int viewWhat; /* Initial view mode (ALL, BEHAVIOR, DATA) */
-
- /* Check if we can find an existing browser for the requested object */
- browserWindow = findBrowser(target);
-
- /* If we can, then select the existing browser */
- if (browserWindow) {
- /* If the window is hidden, make it visible */
- if (!((WindowPeek)browserWindow)->visible) ShowWindow(browserWindow);
- SelectWindow(browserWindow);
- return;
- }
-
- /* Otherwise, open a new browser window for the requested object */
-
- /* First, check if the currently selected window is a browser window */
- frontWindow = FrontWindow();
- wKind = getWindowKind(frontWindow);
-
- /* If the front window is a browser window, then we'll
- duplicate the view mode information from that window.
- */
- if (wKind == BrowserWKind || wKind == CloneBrWKind) {
- iconList = getBrowserIcons(frontWindow);
-
- /* If we are opening a clone family, always display both data and behavior */
- if (browserKind == CloneBrWKind)
- viewWhat = ALL;
- else viewWhat = getViewMode(iconList);
- columns = ((*iconList)->dataBounds).right;
- }
- /* Otherwise, use the default view mode settings */
- /* (defaults: view both data and behavior, one column display) */
- else {
- viewWhat = ALL;
- columns = 1;
- }
-
- /* Build a new window */
- browserWindow = buildWindow("\p");
- ShowWindow(browserWindow);
-
- GetPort(&savePort);
- SetPort(browserWindow);
-
- TextFont(newYork);
- TextFace(0);
- TextSize(10);
-
- SetPort(savePort);
-
- /* Change the window kind to the requested kind */
- thisWinfo = (WINFO*)GetWRefCon(browserWindow);
- thisWinfo->wKind = browserKind;
-
- /* Store the window identifier to the appropriate field */
- setBrowserIdent(browserWindow, windowIdent);
-
- /*
- If there are no previous browser windows open,
- create a new task called 'browserTask', and set
- it to execute the shell in the root context.
-
- This task will allow many commands given from the browser
- to be executed on background, thus making the browser snappier.
- */
- if (browserCount == 0) {
- TASK** tempUp = up;
-
- browserTask = buildTask();
- setTaskBehavior(browserTask, oShell);
- setTaskCWD(browserTask, oUserRoot);
-
- /* Browser task does not normally refer to any window */
- (*browserTask)->window = NIL;
-
- /* Instead, its output goes to '/dev/null' :-) */
- /* and error messages to the console */
- up = browserTask;
- errfile = confile;
- up = tempUp;
-
- /* Browser task also has its own error handler */
- /* to avoid deadlocks as a result of errors within */
- /* critical regions (which are used for method redefinitions) */
- textToKeyBuffer(browserTask, "' brError MY error !");
- crsToKeyBuffer(browserTask);
-
- activateTask(browserTask);
- }
-
- /* Browser window refers to an icon list via its WINFO structure */
- iconList = buildIconList(browserWindow, target, LastBrowser, columns, viewWhat);
- setBrowserIcons(browserWindow, iconList);
- LActivate(TRUE, iconList);
-
- LastBrowser = browserWindow;
- browserCount++;
-
- SelectWindow(browserWindow);
- }
-
-
- /* Reuse a previous browser window by making it display another object */
-
- void reuseBrowser(target, windowIdent, oldBrowser, newKind)
- OBJECT* target; /* The object to be browsed */
- char* windowIdent; /* The (partial) window name */
- WindowPtr oldBrowser; /* An existing browser window */
- int newKind; /* The new browser kind (BrowserWKind, CloneBrWKind) */
- {
- WindowPtr existingBrowser;
- WINFO* thisWinfo;
-
- /* Check if we can find an existing browser for the requested object */
- existingBrowser = findBrowser(target);
-
- /* If we can, then select the existing browser */
- /* And delete the old one */
- if (existingBrowser) {
- deleteBrowser(oldBrowser);
- SelectWindow(existingBrowser);
- return;
- }
-
- /* Change the browser task context to the requested object */
- setBrowserTarget(oldBrowser, target);
-
- /* Change the window kind to the requested kind */
- thisWinfo = (WINFO*)GetWRefCon(oldBrowser);
- thisWinfo->wKind = newKind;
-
- /* Store the window identifier to the appropriate field */
- setBrowserIdent(oldBrowser, windowIdent);
-
- /* Update the browser view using the new target */
- /* and old parameters from the LINFO structure */
- updateBrowser(oldBrowser);
- }
-
-
- /* Finalize and delete a given browser */
-
- void deleteBrowser(browserWindow)
- WindowPtr browserWindow;
- {
- ListHandle iconList = getBrowserIcons(browserWindow);
-
- if (browserCount > 1 || (browserCount == 1 && killTask(browserTask))) {
- unlinkBrowser(browserWindow);
- deleteIconList(iconList);
- deleteWinfo(browserWindow);
- DisposeWindow(browserWindow);
- if (--browserCount == 0) browserTask = NIL;
- }
- else fprintf(confile, "== Cannot delete the only active task in the system ==\n");
- }
-
-
- /* Unlink the given browser from the browser list */
-
- void unlinkBrowser(browserWindow)
- WindowPtr browserWindow;
- {
- WindowPtr prevBr = NIL;
- WindowPtr thisBr = LastBrowser;
-
- while (thisBr) {
- if (browserWindow == thisBr) {
- if (!prevBr) LastBrowser = getPrevBrowser(thisBr);
- else setPrevBrowser(prevBr, getPrevBrowser(thisBr));
- return;
- }
- prevBr = thisBr;
- thisBr = getPrevBrowser(thisBr);
- }
- }
-
-
- /* Given an object, find the possible corresponding browser from the browser list */
-
- WindowPtr findBrowser(target)
- OBJECT* target;
- {
- WindowPtr thisBr = LastBrowser;
-
- while (thisBr) {
- if (getBrowserTarget(thisBr) == target) return(thisBr);
- thisBr = getPrevBrowser(thisBr);
- }
- return(NIL);
- }
-
-
- /* Update the view of the given browser */
-
- void refreshBrowser(browserWindow)
- WindowPtr browserWindow;
- {
- ListHandle iconList = getBrowserIcons(browserWindow);
- OBJECT* cwd = getBrowserTarget(browserWindow);
- CONTEXT* thisContext = getContext(cwd);
- PAIR* thisPair = thisContext->firstPair;
- int viewMode = getViewMode(iconList);
- Cell cell;
- short len;
- OBJECT* object;
- PAIR* valuePair;
- int stillMore;
- int count;
-
- /*
- If we are displaying a clone family, we should remove the possible extra
- slots from the end of the object by optimizing the list
- */
- if (getWindowKind(browserWindow) == CloneBrWKind) optimizeList((LIST*)cwd);
-
- /* Resize the Mac Icon List by counting the number of cells in the object */
- resizeIconList(iconList, cwd);
-
- /* Display each property in the object in the Icon List */
- cell.h = 0; cell.v = 0;
- while (thisPair = getNextMaskedPair(thisPair, viewMode)) {
- int pairKind = recognizeObject(thisPair->ofa);
- int hidden = thisPair->ffa & HiddenFlag;
-
- switch (pairKind) {
- case PRIMITIVE:
- len = sprintf(charbuffer, "%s %s", asString(pairKind, hidden), thisPair->nfa);
- break;
-
- case REF:
- case VAR:
- case CONST:
- {
- switch (pairKind) {
- case REF: object = *getREFslot(thisPair); break;
- case VAR: object = *getVARslot(cwd, thisPair); break;
- case CONST: object = *getREFslot(thisPair); break;
- }
-
- if (isContextObject(object)) {
- if (valuePair = findTypeForward(object))
- len = sprintf(charbuffer, "%s %s (%s)", asString(pairKind, hidden),
- thisPair->nfa, valuePair->nfa);
- else len = sprintf(charbuffer, "%s %s (<no type>:%d)", asString(pairKind, hidden),
- thisPair->nfa, object);
- }
- else len = sprintf(charbuffer, "%s %s (%d)", asString(pairKind, hidden),
- thisPair->nfa, object);
- break;
- }
- case METHOD:
- len = sprintf(charbuffer, "%s %s", asString(pairKind, hidden), thisPair->nfa);
- break;
- }
-
- LSetCell(charbuffer, len, cell, iconList);
- stillMore = LNextCell(TRUE, TRUE, &cell, iconList);
- thisPair = thisPair->sfa;
- }
-
- if (viewMode != BEHAVIOR) {
- /* Add the possible anonymous array slots to the end of the icon list */
- count = AnonymousSlots;
- while (count) {
- object = (OBJECT*)*((int*)cwd->mfa + cwd->sfa - count);
- if (isContextObject(object)) {
- if (valuePair = findTypeForward(object))
- len = sprintf(charbuffer, "<%d> (%s:%d) ", cwd->sfa-count-1, valuePair->nfa, object);
- else len = sprintf(charbuffer, "<%d> (<no type>:%d) ", cwd->sfa-count-1, object);
- }
- else len = sprintf(charbuffer, "<%d> (%d) ", cwd->sfa-count-1, object);
-
- LSetCell(charbuffer, len, cell, iconList);
- stillMore = LNextCell(TRUE, TRUE, &cell, iconList);
- count--;
- }
- }
-
- /* Empty the rest of the cells in the Icon List */
- if (stillMore) {
- /* Old implementation:
- // LClrCell(cell, iconList);
- // while (LNextCell(TRUE, TRUE, &cell, iconList)) LClrCell(cell, iconList);
- */
- LSetCell(" ", 3, cell, iconList);
- while (LNextCell(TRUE, TRUE, &cell, iconList))
- LSetCell(" ", 3, cell, iconList);
- }
- }
-
-
- /* Update the title and view of the given browser */
-
- void updateBrowser(browserWindow)
- WindowPtr browserWindow;
- {
- OBJECT* cwd = getBrowserTarget(browserWindow);
- CONTEXT* context = getContext(cwd);
-
- /* Update the title of the window with the current type information */
- /* This operation is rather time consuming */
- updateBrowserTitle(browserWindow);
-
- /* Refresh the contents of the browser */
- refreshBrowser(browserWindow);
-
- /*
- For security, perform some integrity checks for the object.
- This allows the user to notice possible memory leak problems etc.
- in his programs earlier before they cause some totally obscure errors.
- Problems will be reported to console along with a three beeps.
-
- However, since rootContext is so big (= time-consuming to check),
- we never perform the integrity checks for that object.
- */
- /* if (context != rootContext) checkIntegrity(context); */
- }
-
-
- /* Update the browser title, using current type information */
-
- void updateBrowserTitle(browserWindow)
- WindowPtr browserWindow;
- {
- OBJECT* cwd = getBrowserTarget(browserWindow);
- int wKind = getWindowKind(browserWindow);
-
- /* Special case: the Root object */
- if (cwd == oUserRoot) {
- SetWTitle(browserWindow, "\pRoot");
- return;
- }
-
- switch (wKind) {
- case BrowserWKind: {
- char* thisName = getBrowserIdent(browserWindow);
- decodeObjectType(thisName, cwd);
- break;
- }
- case CloneBrWKind: {
- OBJECT* object = (OBJECT*)fetchFromList((LIST*)cwd, 1);
-
- if (object == oUserRoot) sprintf(charbuffer, "Root clone family");
- else {
- PAIR* thisPair = findTypeForward(object);
- if (thisPair)
- sprintf(charbuffer, "%s clone family", thisPair->nfa);
- else sprintf(charbuffer, "<anon> clone family");
- }
- CtoPstr(charbuffer);
- break;
- }
- }
- SetWTitle(browserWindow, charbuffer);
- }
-
-
- /* Change the number of columns in the browser */
-
- void recolumnBrowser(browserWindow, newCols)
- WindowPtr browserWindow;
- int newCols;
- {
- ListHandle iconList = getBrowserIcons(browserWindow);
- OBJECT* cwd = getBrowserTarget(browserWindow);
- WindowPtr oldPrevBr = getPrevBrowser(browserWindow);
- int oldCols = ((*iconList)->dataBounds).right;
- int oldViewMode = getViewMode(iconList);
-
- if (newCols == oldCols) return;
-
- EraseRect(&browserWindow->portRect);
- deleteIconList(iconList);
- iconList = buildIconList(browserWindow, cwd, oldPrevBr, newCols, oldViewMode);
- setBrowserIcons(browserWindow, iconList);
-
- LActivate(TRUE, iconList);
- updateBrowser(browserWindow);
- DrawGrowIcon(browserWindow);
- }
-
-
- /* React to a double click */
-
- void handleDoubleClick(browserWindow, optKey)
- WindowPtr browserWindow;
- int optKey;
- {
- ListHandle iconList = getBrowserIcons(browserWindow);
- OBJECT* cwd = getBrowserTarget(browserWindow);
- CONTEXT* context = getContext(cwd);
- Cell cell = LLastClick(iconList);
- int index = cellToIndex(iconList, cell);
- int viewMode = getViewMode(iconList);
- PAIR* thisPair = indexedFind(context, index, viewMode);
- int pairKind;
- OBJECT* object;
-
- /* If the object contains a pair for the selected cell */
- if (thisPair) {
- switch (pairKind = recognizeObject(thisPair->ofa)) {
- case PRIMITIVE:
- if (optKey) {
- /* If option key is pressed during double click, execute the primitive */
- numberToKeyBuffer(browserTask, (int)cwd);
- textToKeyBuffer(browserTask, " CD");
- crsToKeyBuffer(browserTask);
- numberToKeyBuffer(browserTask, thisPair->ofa);
- textToKeyBuffer(browserTask, " execute");
- crsToKeyBuffer(browserTask);
- }
- else SysBeep(1);
- break;
-
- case REF:
- case VAR:
- case CONST:
- {
- switch (pairKind) {
- case REF: object = *getREFslot(thisPair); break;
- case VAR: object = *getVARslot(cwd, thisPair); break;
- case CONST: object = *getREFslot(thisPair); break;
- }
-
- if (isContextObject(object)) {
- if (optKey) reuseBrowser(object, thisPair->nfa, browserWindow, BrowserWKind);
- else openBrowser(object, thisPair->nfa, BrowserWKind);
- }
- else SysBeep(1);
- break;
- }
-
- case METHOD: {
- if (optKey) {
- /* If option key is pressed during double click, execute the method */
- numberToKeyBuffer(browserTask, (int)cwd);
- textToKeyBuffer(browserTask, " CD");
- crsToKeyBuffer(browserTask);
- numberToKeyBuffer(browserTask, thisPair->ofa);
- textToKeyBuffer(browserTask, " execute");
- crsToKeyBuffer(browserTask);
- }
- else {
- WindowPtr methodWindow;
- TASK** tempUp = up;
- PAIR* typePair;
-
- yieldTo(browserTask);
- pushContext((int*)cwd);
-
- if (typePair = findTypeForward(cwd))
- sprintf(charbuffer, "%s METHOD %s", typePair->nfa, thisPair->nfa);
- else sprintf(charbuffer, "METHOD %s", thisPair->nfa);
- CtoPstr(charbuffer);
-
- /* Set the output of browser task temporarily to a window */
- methodWindow = buildTEWindow(charbuffer);
- (*browserTask)->window = (int*)methodWindow;
- ShowWindow(methodWindow);
- outfile = (FILE*)0;
-
- setMethodContext(methodWindow, cwd);
- setMethodPair(methodWindow, thisPair);
-
- SelectWindow(methodWindow);
- decompile(thisPair->ofa);
-
- /* Set the output of browser task back to console */
- (*browserTask)->window = NIL;
- /* outfile = confile; */
- errfile = confile;
- theTask = NIL;
- theText = NIL;
-
- (void)popContext();
- yieldTo(tempUp);
- }
- break;
- }
- }
- }
- else if (AnonymousSlots) {
- /* No matching pair -> handle the possible anonymous slot access */
- int position = index - MaskedPairs;
- object = (OBJECT*)*((int*)cwd->mfa + position + 1);
-
- if (isContextObject(object)) {
- if (optKey) reuseBrowser(object, NIL, browserWindow, BrowserWKind);
- else openBrowser(object, NIL, BrowserWKind);
- }
- else SysBeep(1);
- }
- }
-
-
- /*
- Open browsers for all the parent or child clone families
- on the basis of the currently selected browser window.
- */
- void browseCloneFamilies(browserWindow, familyStr)
- WindowPtr browserWindow;
- char* familyStr; /* parameter string should be either "parent" or "child" */
- {
- OBJECT* cwd;
- LIST* cwdFamily;
- int index;
-
- /*
- This operation can be invoked from both "normal" browser windows
- and from clone family windows. We must initialize the variables
- differently depending on this.
- */
- switch (getWindowKind(browserWindow)) {
- case BrowserWKind:
- cwd = getBrowserTarget(browserWindow);
- if (strcmp(familyStr, "parent") == 0)
- cwdFamily = getContext(cwd)->parentFamilies;
- else cwdFamily = getContext(cwd)->childFamilies;
- break;
-
- case CloneBrWKind:
- /* Note: this assumes that the clone family has at least one member */
- cwd = fetchFromList((LIST*)getBrowserTarget(browserWindow), 1);
- if (strcmp(familyStr, "parent") == 0)
- cwdFamily = getContext(cwd)->parentFamilies;
- else cwdFamily = getContext(cwd)->childFamilies;
- break;
- }
-
- /* If the family list is empty -> do nothing */
- if (cwdFamily->logicalSize == 0) return;
-
- /* Otherwise, open a clone family browser for each of the members */
- for (index = 1; index <= cwdFamily->logicalSize; index++) {
- LIST* thisFamily = (LIST*)fetchFromList(cwdFamily, index);
-
- if (!isContextObject((OBJECT*)thisFamily)) {
- fprintf(confile, "== Integrity error detected: %s family is not a valid object ==\n", familyStr);
- reportIntegrityError();
- ownLongJmp();
- }
-
- /* The window will be opened only if the family contains members */
- /* (if the system works correctly, all the families do contain members) */
- if (thisFamily->logicalSize > 0) {
-
- /*
- Since we may have to open multiple windows,
- set the browser task to open the browser on background
- so as to allow multitasking to operate without delays.
- */
-
- /* Remember that 'numberToKeyBuffer' changes 'charbuffer' */
- numberToKeyBuffer(browserTask, (int)thisFamily);
- textToKeyBuffer(browserTask, " cfBrowse");
- crsToKeyBuffer(browserTask);
- }
- else {
- fprintf(confile, "== Integrity error detected: empty %s family ==\n", familyStr);
- reportIntegrityError();
- ownLongJmp();
- }
- }
- }
-
-
- /* Assign the given object to the selected slot in the target window */
- /*
- The object will be assigned only if there is exactly one slot selected
- in the icon list, and that slot is either a shared variable (REF) or
- an instance variable (VAR)
-
- Actually, the same checks are performed in 'doBrowserDisable', but they
- are kept here for safety.
- */
- void assignObject(browserWindow, source)
- WindowPtr browserWindow; /* The target window */
- OBJECT* source; /* The object to be assigned */
- {
- OBJECT* cwd = getBrowserTarget(browserWindow);
- ListHandle iconList = getBrowserIcons(browserWindow);
- int selected = countSelectedCells(iconList);
-
- if (selected != 1) {
- SysBeep(1);
- fprintf(confile, "== Exactly one variable slot must be active during assignment ==\n");
- return;
- }
- else {
- PAIR* thisPair;
- OBJECT* target;
- OBJECT** slot;
- int pairKind;
- Cell cell;
-
- cell.h = -1; cell.v = 0;
- (void)nextSelectedCell(iconList, &cell);
-
- thisPair = cellToPair(browserWindow, cell);
- if (!thisPair) {
- SysBeep(1);
- fprintf(confile, "== The target slot in assignment must be either a VAR or a REF ==\n");
- return;
- }
-
- target = thisPair->ofa;
- pairKind = recognizeObject(target);
-
- switch (pairKind) {
- case REF:
- case VAR:
- switch (pairKind) {
- case REF: slot = getREFslot(thisPair); break;
- case VAR: slot = getVARslot(cwd, thisPair); break;
- }
- *slot = source;
- updateBrowser(browserWindow);
-
- /* Select the second topmost window so as to confirm */
- /* which object has been assigned */
- openBrowser(source, thisPair->nfa, BrowserWKind);
- break;
- default:
- SysBeep(1);
- fprintf(confile, "== The target slot in assignment must be either a VAR or a REF ==\n");
- break;
- }
- }
- }
-
-
- /* Open command shell (value editor) window for the given object */
-
- void openShellForThis(object)
- OBJECT* object;
- {
- TASK** newTask = buildTask();
- WindowPtr newWindow;
- PAIR* typePair;
-
- /* In the browser mode, we copy the initial
- context from the current browser task.
-
- The execution will be started from 'shell' rather than 'boot'.
- */
- setTaskBehavior(newTask, oShell);
- setTaskCWD(newTask, object);
-
- typePair = findTypeForward(object);
- if (typePair)
- sprintf(charbuffer, "Command Shell (%s:%d)", typePair->nfa, object);
- else sprintf(charbuffer, "Command Shell (object %d)", object);
- CtoPstr(charbuffer);
-
- /* Build a new TextEdit window for the newly created task */
- newWindow = buildTEWindow(charbuffer);
- if (newWindow) {
- (*newTask)->window = (int*)newWindow;
- ShowWindow(newWindow);
- SelectWindow(newWindow);
- }
- activateTask(newTask);
- }
-
-
- /* ------------------------------------------------------------------------ */
- /* Icon List operations */
-
- /* Build an icon list structure, using the Mac Toolbox List Manager Package */
- /* Note that these lists have nothing to do with the lists defined in 'lists.h' */
-
- ListHandle buildIconList(thisWindow, target, prevBrowser, columnNumber, viewWhat)
- WindowPtr thisWindow;
- OBJECT* target;
- WindowPtr prevBrowser;
- int columnNumber;
- int viewWhat;
- {
- ListHandle iconList;
- Point cSize;
- Rect viewRect, boundsRect;
-
- /* Set the cell dimensions (horizontal and vertical) */
- /* Defaults are h: 480 / cols and v: 18 */
- cSize.h = ICONLINELENGTH / columnNumber;
- cSize.v = ICONCELLHEIGHT;
-
- boundsRect.left = 0;
- boundsRect.top = 0;
- boundsRect.right = columnNumber;
- boundsRect.bottom = 1;
-
- BlockMove(&thisWindow->portRect, &viewRect, sizeof(Rect));
- viewRect.right -= 15; /* Must be 15 */
- viewRect.bottom -= 15; /* Must be 15 */
-
- /* Build a new Mac Toolbox List */
- iconList = LNew(&viewRect, /* Screen size of the icon list */
- &boundsRect, /* Number of rows and columns */
- cSize, /* Cell size */
- 333, /* List definition (LDEF) resource id, default=0/custom=333 */
- thisWindow, /* The window in which the icon list resides */
- TRUE, /* drawIt (cell drawing is enabled) */
- TRUE, /* hasGrow (there is a size box) */
- TRUE, /* scrollHoriz (there is a horizontal scroll bar) */
- TRUE); /* scrollVert (there is a vertical scroll bar) */
-
- /* Empty cells should not be highlighted */
- (*iconList)->selFlags |= lNoNilHilite;
-
- /* Create the icon list information structure */
- (*iconList)->refCon = (long)createLinfo(viewWhat, target, prevBrowser);
-
- return(iconList);
- }
-
-
- /* Delete an icon list structure */
-
- void deleteIconList(iconList)
- ListHandle iconList;
- {
- LINFO* thisLinfo = (LINFO*)(*iconList)->refCon;
-
- /* Delete the associated information structure */
- deleteLinfo(thisLinfo);
-
- /* Delete the Mac Toolbox List itself */
- LDispose(iconList);
- }
-
-
- /* Add or remove columns from the icon list if needed */
-
- void resizeIconList(iconList, cwd)
- ListHandle iconList;
- OBJECT* cwd;
- {
- CONTEXT* context = getContext(cwd);
- int viewMode = getViewMode(iconList);
- int cols = ((*iconList)->dataBounds).right;
- int lastRow;
- int delta; /* Change in row count */
- Cell cell;
-
- /* Set the values of the global icon list item counts */
-
- /* Number of appropriate pairs in the current object */
- /* This is a global variable */
- MaskedPairs = maskedCountPairs(context, viewMode);
-
- /* Number of anynymous (array) slots in the current object */
- /* This is a global variable */
- AnonymousSlots = countArraySlots(cwd);
-
- /* In behavior display mode, we don't display the anonymous array slots */
- /* so they will not be added to the cell count when resizing the icon list */
- /* CellsInTotal is also a global variable that tells how many cells/icons the */
- /* current browser has */
- if (viewMode != BEHAVIOR)
- CellsInTotal = MaskedPairs + AnonymousSlots;
- else CellsInTotal = MaskedPairs;
-
- lastRow = (CellsInTotal+cols-1) / cols;
- delta = lastRow - ((*iconList)->dataBounds).bottom;
-
- if (delta > 0) { /* Lines must be added */
- /* second argument must be bigger than biggest possible column number */
- LAddRow(delta, -1, iconList);
- return;
- }
- if (delta < 0) { /* Lines must be deleted */
- LDelRow(-delta, 0, iconList);
- }
- }
-
-
- /* Determine the correct size for the browser */
- /* This routine is used for zoom box operation */
-
- void determineBrowserWindowSize(browserWindow)
- WindowPtr browserWindow;
- {
- ListHandle iconList = getBrowserIcons(browserWindow);
- int columns = ((*iconList)->dataBounds).right;
- WStateData** wDataHdl;
- Rect newRect;
- int offsetLeft = 0 - browserWindow->portBits.bounds.left;
- int offsetTop = 0 - browserWindow->portBits.bounds.top;
- int width;
- int height;
-
- if (columns == 1) {
- width = ICONLINELENGTH / 2 + SCROLLBARWIDTH;
- height = CellsInTotal*ICONCELLHEIGHT + SCROLLBARWIDTH + 6;
- }
- else {
- width = ICONLINELENGTH + SCROLLBARWIDTH;
- height = (((CellsInTotal+columns-1) / 4) * ICONCELLHEIGHT) + SCROLLBARWIDTH + 6;
- }
-
- /* Ensure that window doesn't become too large for the screen */
- if (height > screenBits.bounds.bottom - (SCROLLBARWIDTH*2 + 15))
- height = screenBits.bounds.bottom - (SCROLLBARWIDTH*2 + 15);
-
- /* Ensure that window doesn't become too small either */
- else if (height < ICONCELLHEIGHT*3 + SCROLLBARWIDTH)
- height = ICONCELLHEIGHT*3 + SCROLLBARWIDTH;
-
- /* Set the calculated browser size for zoom box usage */
- SetRect(&newRect, offsetLeft, offsetTop, offsetLeft + width, offsetTop + height);
- wDataHdl = (WStateData**)((WindowPeek)browserWindow)->dataHandle;
- BlockMove(&newRect, &(*wDataHdl)->stdState, sizeof(Rect));
- }
-
-
- /* Return true if there is yet another selected cell in the icon list */
- /* The selected cell is returned in parameter 'nextCell' */
-
- int nextSelectedCell(iconList, nextCell)
- ListHandle iconList;
- Cell* nextCell;
- {
- int cols = (*iconList)->dataBounds.right;
- int rows = (*iconList)->dataBounds.bottom;
- int selected = FALSE;
-
- while (nextCell->v < rows) {
-
- nextCell->h++;
-
- if (nextCell->h >= cols) {
- nextCell->h = 0;
- nextCell->v++;
- }
-
- if (selected = LGetSelect(FALSE, nextCell, iconList)) break;
- }
-
- return(selected);
- }
-
-
- /* Return true if there is yet another selected cell in the icon list */
- /* The selected cell is returned in parameter 'prevCell' */
-
- int prevSelectedCell(iconList, prevCell)
- ListHandle iconList;
- Cell* prevCell;
- {
- int cols = (*iconList)->dataBounds.right;
- int selected = FALSE;
-
- while (prevCell->v >= 0) {
-
- prevCell->h--;
-
- if (prevCell->h < 0) {
- prevCell->h = cols-1;
- prevCell->v--;
- }
-
- if (selected = LGetSelect(FALSE, prevCell, iconList)) break;
- }
-
- return(selected);
- }
-
-
- /* Return the number of selected cells in the icon list */
-
- int countSelectedCells(iconList)
- ListHandle iconList;
- {
- Cell cell;
- int count = 0;
-
- cell.h = -1; cell.v = 0;
-
- while (nextSelectedCell(iconList, &cell)) count++;
- return(count);
- }
-
-
- /* Add a new cell (pair) to the object being browsed */
-
- void addNewCell(browserWindow, slotType, name)
- WindowPtr browserWindow;
- int slotType;
- char* name;
- {
- OBJECT* cwd = getBrowserTarget(browserWindow);
- CONTEXT* context;
- PAIR* newPair;
- OBJECT* object;
-
- /* The current version does not support addition of cells to descendants */
- if (whoToModify == DERIVATIVES) {
- SysBeep(1);
- fprintf(confile, "== This version does not support addition of slots in the 'derivatives' ==\n");
- fprintf(confile, "== mode (use 'clone family' mode and CUT/COPY/PASTE instead) ==\n");
- return;
- }
-
- /* Create a new clone family if needed */
- if (whoToModify == THIS_ONLY) deriveObject(cwd);
-
- /* Add the appropriate slot */
- switch (slotType) {
- case REF:
- object = createClosure(2);
- object->mfa->efa = (int*)oREF;
- break;
- case REF+8:
- pBuildDir();
- object = createClosure(2);
- object->mfa->efa = (int*)oREF;
- object->mfa->pfa = (int*)popData();
- break;
- case VAR:
- object = createClosure(2);
- object->mfa->efa = (int*)oVAR;
- object->mfa->pfa = (int*)cwd->sfa;
- resizeFamilyMembers(cwd, cwd->sfa+1);
- break;
- case CONST:
- object = createClosure(2);
- object->mfa->efa = (int*)oSharedConst;
- break;
- case METHOD:
- object = createClosure(1);
- break;
- }
-
- context = getContext(cwd);
- newPair = addPair(context, name, object);
-
- /* Possibly change the object's clone family */
- confirmObjectType(cwd, whoToModify, ADDING_SOMETHING);
- updateBrowser(browserWindow);
- }
-
-
- /* Remove a given cell (pair) from the object being browsed */
-
- void removeCell(browserWindow, cell)
- WindowPtr browserWindow;
- Cell cell;
- {
- PAIR* thisPair = cellToPair(browserWindow, cell);
-
- if (!thisPair) return;
-
- unlinkPair(thisPair);
- free(thisPair);
- }
-
-
- /* Change encapsulation of a given cell (pair) */
-
- void hideShowCell(browserWindow, cell)
- WindowPtr browserWindow;
- Cell cell;
- {
- PAIR* thisPair = cellToPair(browserWindow, cell);
-
- if (!thisPair) return;
-
- if (thisPair->ffa & HiddenFlag)
- /* reset the hidden flag */
- thisPair->ffa &= ~HiddenFlag;
- else
- /* raise the hidden flag */
- thisPair->ffa |= HiddenFlag;
- }
-
-
- /* Add a character to the property name in a cell */
-
- void addToCell(iconList, cell, c)
- ListHandle iconList;
- Cell cell;
- char c;
- {
- char qualifier[16];
- char name[128];
- short count = CHARBUFLEN;
- int index = cellToIndex(iconList, cell);
-
- if (index > MaskedPairs) { SysBeep(1); return; }
-
- LGetCell(charbuffer, &count, cell, iconList);
- charbuffer[count] = 0;
-
- /* We have to initialize name, because charbuffer may not contain two words */
- name[0] = 0;
- sscanf(charbuffer, "%s %s", qualifier, name);
- name[strlen(name)+1] = 0;
- name[strlen(name)] = c;
- sprintf(charbuffer, "%s %s", qualifier, name);
-
- LSetCell(charbuffer, (short)(strlen(qualifier)+strlen(name)+1), cell, iconList);
- }
-
-
- /* Remove a character from the property name in a cell */
-
- void removeFromCell(iconList, cell)
- ListHandle iconList;
- Cell cell;
- {
- char qualifier[16];
- char name[128];
- short count = CHARBUFLEN;
- int index = cellToIndex(iconList, cell);
-
- if (index > MaskedPairs) { SysBeep(1); return; }
-
- LGetCell(charbuffer, &count, cell, iconList);
- charbuffer[count] = 0;
-
- name[0] = 0;
- sscanf(charbuffer, "%s %s", qualifier, name);
- if (strlen(name)) {
- name[strlen(name)-1] = 0;
- sprintf(charbuffer, "%s %s", qualifier, name);
- LSetCell(charbuffer, (short)(strlen(qualifier)+strlen(name)+1), cell, iconList);
- }
- else SysBeep(1);
- }
-
-
- /* Rename the property in a cell using the possibly changed name */
-
- void renameCell(browserWindow, cell)
- WindowPtr browserWindow;
- Cell cell;
- {
- OBJECT* cwd = getBrowserTarget(browserWindow);
- ListHandle iconList = getBrowserIcons(browserWindow);
- PAIR* thisPair;
- char qualifier[16];
- char name[128];
- short count = CHARBUFLEN;
-
- /* The current version does not support renaming of cells to descendants */
- if (whoToModify == DERIVATIVES) {
- SysBeep(1);
- fprintf(confile, "== This version does not support renaming of slots in the 'derivatives' ==\n");
- fprintf(confile, "== mode (use 'clone family' mode and CUT/COPY/PASTE instead) ==\n");
- return;
- }
-
- /* Create a new clone family if needed */
- if (whoToModify == THIS_ONLY) deriveObject(cwd);
-
- thisPair = cellToPair(browserWindow, cell);
- if (!thisPair) return;
-
- LGetCell(charbuffer, &count, cell, iconList);
- charbuffer[count] = 0;
-
- name[0] = 0;
- sscanf(charbuffer, "%s %s", qualifier, name);
- if (strlen(name) && thisPair) {
- renamePair(thisPair, allocStrCpy(name));
- /* Possibly change the object's clone family */
- confirmObjectType(cwd, whoToModify, RENAMING_SOMETHING);
- updateBrowser(browserWindow);
- }
- else SysBeep(1);
- }
-
-
- /* Convert cells to one-dimensional indexes */
- /* Indexing starts from number one */
-
- int cellToIndex(iconList, cell)
- ListHandle iconList;
- Cell cell;
- {
- return (cell.v * ((*iconList)->dataBounds).right + cell.h + 1);
- }
-
-
- /* Given a cell, return the corresponding pair */
-
- PAIR* cellToPair(browserWindow, cell)
- WindowPtr browserWindow;
- Cell cell;
- {
- ListHandle iconList = getBrowserIcons(browserWindow);
- OBJECT* cwd = getBrowserTarget(browserWindow);
- CONTEXT* context = getContext(cwd);
- int index = cellToIndex(iconList, cell);
- int viewMode = getViewMode(iconList);
-
- return(indexedFind(context, index, viewMode));
- }
-
-
- /* Find the correct pair in the context, taking the mask into account */
-
- PAIR* indexedFind(context, index, viewMode)
- CONTEXT* context;
- int index;
- int viewMode;
- {
- switch (viewMode) {
- case ALL:
- return(findAllAsIndexed(context, index));
- break;
- case DATA:
- return(findDataAsIndexed(context, index));
- break;
- case BEHAVIOR:
- return(findOperAsIndexed(context, index));
- break;
- }
- }
-
-
- /* Get the next pair with the desired search mask */
-
- PAIR* getNextMaskedPair(thisPair, viewMode)
- PAIR* thisPair;
- int viewMode;
- {
- while (thisPair) {
- switch (viewMode) {
- case ALL:
- return(thisPair);
- break;
- case DATA:
- if (thisPair->ofa) switch(recognizeObject(thisPair->ofa)) {
- case REF:
- case VAR:
- case CONST:
- return(thisPair);
- }
- break;
- case BEHAVIOR:
- if (thisPair->ofa) switch(recognizeObject(thisPair->ofa)) {
- case PRIMITIVE:
- case METHOD:
- return(thisPair);
- }
- break;
- }
- thisPair = thisPair->sfa;
- }
- return(NIL);
- }
-
-
- /* Count the number of pairs, taking the mask into account */
-
- int maskedCountPairs(context, viewMode)
- CONTEXT* context;
- int viewMode;
- {
- switch (viewMode) {
- case ALL:
- return(countAllPairs(context));
- break;
- case DATA:
- return(countDataPairs(context));
- break;
- case BEHAVIOR:
- return(countOperPairs(context));
- break;
- }
- }
-
-
- /* Check if an object is an array rather than conventional object */
- /*
- Return zero if the object is a normal object.
- Return the count of anonymous data slots otherwise.
- */
- int countArraySlots(ctxtObject)
- OBJECT* ctxtObject;
- {
- CONTEXT* thisContext = getContext(ctxtObject);
- PAIR* thisPair = thisContext->firstPair;
- int array = TRUE;
-
- while (thisPair) {
- if (recognizeObject(thisPair->ofa) == VAR) {
- array = FALSE;
- break;
- }
- thisPair = thisPair->sfa;
- }
-
- if (array) return(ctxtObject->sfa - DATAOFFSET);
- else return(0);
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Auxiliary operations */
-
- /* Build a textual description of an object */
- /* The resulting format is:
- 'name (type)',
- where name is either name or '<anon>', and
- type is either "type:id#" or "id#".
-
- The result will be stored in global variable 'charbuffer'.
- */
-
- void decodeObjectType(thisName, object)
- char* thisName;
- OBJECT* object;
- {
- PAIR* typePair = findTypeForward(object);
-
- if (thisName == NIL) thisName = "<anon>";
-
- if (typePair)
- sprintf(charbuffer, "%s (%s:%d)", thisName, typePair->nfa, object);
- else sprintf(charbuffer, "%s (%d)", thisName, object);
-
- CtoPstr(charbuffer);
- }
-
-
- /* Return an appropriate string */
-
- char* asString(objectKind, hidden)
- int objectKind;
- int hidden;
- {
- char* string;
-
- switch(objectKind) {
- case PRIMITIVE: string = " P"; break;
- case REF: string = " R"; break;
- case VAR: string = " V"; break;
- case CONST: string = " C"; break;
- case METHOD: string = " M"; break;
- }
-
- /* 'Hidden' contains the encapsulation information. */
-
- if (hidden) *string = '_';
- else *string = '^';
-
- return(string);
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Icon list information field operations */
-
- /* Create a list information structure */
- /*
- Each icon list must contain one of these structures stored
- its 'RefCon' field.
- */
-
- LINFO* createLinfo(viewMode, target, lastBrowser)
- int viewMode; /* Icon list view mode (see 'portGlobal.h') */
- OBJECT* target;
- WindowPtr lastBrowser;
- {
- LINFO* newLinfo = (LINFO*)mycalloc(1, sizeof(LINFO));
-
- newLinfo->lMode = viewMode;
- newLinfo->target = target;
- newLinfo->prevBrowser = lastBrowser;
-
- return(newLinfo);
- }
-
-
- /* Delete a list information structure */
-
- void deleteLinfo(thisLinfo)
- LINFO* thisLinfo;
- {
- free(thisLinfo);
- }
-
-
- /* Return view mode info */
-
- int getViewMode(iconList)
- ListHandle iconList;
- {
- LINFO* thisLinfo = (LINFO*)(*iconList)->refCon;
-
- if (thisLinfo) return(thisLinfo->lMode);
- else return(ALL);
- }
-
-
- /* Set view mode info */
-
- void setViewMode(iconList, viewMode)
- ListHandle iconList;
- int viewMode;
- {
- LINFO* thisLinfo = (LINFO*)(*iconList)->refCon;
-
- if (thisLinfo) thisLinfo->lMode = viewMode;
- }
-
-
- /* Given a browser window, get the object being browsed */
-
- OBJECT* getBrowserTarget(browserWindow)
- WindowPtr browserWindow;
- {
- ListHandle iconList = getBrowserIcons(browserWindow);
- LINFO* thisLinfo;
-
- if (!iconList) return(NIL);
-
- thisLinfo = (LINFO*)(*iconList)->refCon;
- if (thisLinfo) return(thisLinfo->target);
- else return(NIL);
- }
-
-
- /* Set the 'target' field of a browser window (stored in iconList's LINFO structure) */
-
- void setBrowserTarget(browserWindow, target)
- WindowPtr browserWindow;
- OBJECT* target;
- {
- ListHandle iconList = getBrowserIcons(browserWindow);
- LINFO* thisLinfo;
-
- if (!iconList) return;
-
- thisLinfo = (LINFO*)(*iconList)->refCon;
- if (thisLinfo) thisLinfo->target = target;
- }
-
-
- /* Given a browser window, get the previous one */
-
- WindowPtr getPrevBrowser(browserWindow)
- WindowPtr browserWindow;
- {
- ListHandle iconList = getBrowserIcons(browserWindow);
- LINFO* thisLinfo;
-
- if (!iconList) return (NIL);
-
- thisLinfo = (LINFO*)(*iconList)->refCon;
- if (thisLinfo) return(thisLinfo->prevBrowser);
- else return(NIL);
- }
-
-
- /* Set the 'prevBrowser' field of a browser window (stored in iconList's LINFO structure) */
-
- void setPrevBrowser(browserWindow, previous)
- WindowPtr browserWindow;
- WindowPtr previous;
- {
- ListHandle iconList = getBrowserIcons(browserWindow);
- LINFO* thisLinfo;
-
- if (!iconList) return;
-
- thisLinfo = (LINFO*)(*iconList)->refCon;
- if (thisLinfo) thisLinfo->prevBrowser = previous;
- }
-
-